/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "securec.h"
#include "sle_ssap_server_parcel.h"
#include "sle_hilog.h"

namespace OHOS {
namespace NearLink {
namespace SleStandard {
SsapServerPropertyParam::SsapServerPropertyParam(const SsapsPropertyParam &param)
{
    Uuid uuid(param.uuid);
    uuid_ = uuid;
    permissions_ = param.permissions;
    opIndication_ = param.opIndication;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }
}

bool SsapServerPropertyParam::Marshalling(Parcel &parcel) const
{
    if (!parcel.WriteParcelable(&uuid_)) {
        return false;
    }
    if(!parcel.WriteUint16(permissions_)) {
        return false;
    }
    if(!parcel.WriteUint32(opIndication_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerPropertyParam *SsapServerPropertyParam::Unmarshalling(Parcel &parcel)
{
    SsapServerPropertyParam *param = new SsapServerPropertyParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerPropertyParam::ReadFromParcel(Parcel &parcel)
{
    std::shared_ptr<Uuid> uuid(parcel.ReadParcelable<Uuid>());
    if (!uuid) {
        return false;
    }
    uuid_ = *uuid;

    if (!parcel.ReadUint16(permissions_)) {
        return false;
    }
    if (!parcel.ReadUint32(opIndication_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerPropertyParam::ConvertToSsapsPropertyParam(SsapsPropertyParam &param) const
{
    param.uuid = uuid_.ConvertToSleUuid();
    param.permissions = (SsapPermissionType)permissions_;
    param.opIndication = (SsapOperateIndication)opIndication_;
    param.valueLen = length_;
    param.value = data_.get();
}

SleErrorCode SsapServerPropertyParam::CheckSsapsPropertyParam(const SsapsPropertyParam &param)
{
    SleErrorCode ret = Uuid::CheckSleUuid(param.uuid);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM, "param server property uuid error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.permissions >= SSAP_PERMISSION_CAN_READ && param.permissions <= 0x1F,
        SLE_ERR_INVALID_PARAM, "param server property permission error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.opIndication >= SSAP_OPERATEIND_BIT_READ && param.opIndication <= 0x13F,
        SLE_ERR_INVALID_PARAM, "param server property indication error!");
    // todo 检查valueLen的上限
    SLE_ASSERT_AND_RETURN_RET_LOG(param.valueLen != 0, SLE_ERR_INVALID_PARAM,
        "param server property value length error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.value, SLE_ERR_INVALID_PARAM,
        "param server property value ptr not init error!");
    return SLE_NO_ERROR;
}

SsapServerDescriptorParam::SsapServerDescriptorParam(const SsapsDescriptorParam &param)
{
    Uuid uuid(param.uuid);
    uuid_ = uuid;
    permissions_ = param.permissions;
    opIndication_ = param.operateInd;
    type_ = param.type;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }
}

bool SsapServerDescriptorParam::Marshalling(Parcel &parcel) const
{
    if (!parcel.WriteParcelable(&uuid_)) {
        return false;
    }
    if(!parcel.WriteUint16(permissions_)) {
        return false;
    }
    if(!parcel.WriteUint32(opIndication_)) {
        return false;
    }
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerDescriptorParam *SsapServerDescriptorParam::Unmarshalling(Parcel &parcel)
{
    SsapServerDescriptorParam *param = new SsapServerDescriptorParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerDescriptorParam::ReadFromParcel(Parcel &parcel)
{
    std::shared_ptr<Uuid> uuid(parcel.ReadParcelable<Uuid>());
    if (!uuid) {
        return false;
    }
    uuid_ = *uuid;

    if (!parcel.ReadUint16(permissions_)) {
        return false;
    }
    if (!parcel.ReadUint32(opIndication_)) {
        return false;
    }
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerDescriptorParam::ConvertToSsapsDescriptorParam(SsapsDescriptorParam &param) const
{
    param.uuid = uuid_.ConvertToSleUuid();
    param.permissions = (SsapPermissionType)permissions_;
    param.operateInd = (SsapOperateIndication)opIndication_;
    param.type = (SsapPropertyType)type_;
    param.valueLen = length_;
    param.value = data_.get();
}

SleErrorCode SsapServerDescriptorParam::CheckSsapsDescriptorParam(const SsapsDescriptorParam &param)
{
    SleErrorCode ret = Uuid::CheckSleUuid(param.uuid);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM, "param server descriptor uuid error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.permissions >= SSAP_PERMISSION_CAN_READ && param.permissions <= 0x1F,
        SLE_ERR_INVALID_PARAM, "param server descriptor permission error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.operateInd >= SSAP_OPERATEIND_BIT_READ && param.operateInd <= 0x13F,
        SLE_ERR_INVALID_PARAM, "param server descriptor indication error!");
    SLE_ASSERT_AND_RETURN_RET_LOG((param.type >= SSAP_PROPERTY_TYPE_VALUE_TYPE && param.type <= SSAP_DESCRIPTOR_TYPE_RFU_TYPE) ||
        param.type == SSAP_DESCRIPTOR_TYPE_CUSTOM_TYPE, SLE_ERR_INVALID_PARAM, "param server descriptor type error!");
    // todo 检查valueLen的上限
    SLE_ASSERT_AND_RETURN_RET_LOG(param.valueLen != 0, SLE_ERR_INVALID_PARAM,
        "param server descriptor value length error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.value, SLE_ERR_INVALID_PARAM,
        "param server descriptor value ptr not init error!");
    return SLE_NO_ERROR;
}

// SsapServerSendRspParam
SsapServerSendRspParam::SsapServerSendRspParam(const SsapsSendRspParam &param)
{
    requestId_ = param.requestId;
    status_ = param.status;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }
}

bool SsapServerSendRspParam::Marshalling(Parcel &parcel) const
{
    if(!parcel.WriteUint16(requestId_)) {
        return false;
    }
    if(!parcel.WriteUint8(status_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerSendRspParam *SsapServerSendRspParam::Unmarshalling(Parcel &parcel)
{
    SsapServerSendRspParam *param = new SsapServerSendRspParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerSendRspParam::ReadFromParcel(Parcel &parcel)
{
    if (!parcel.ReadUint16(requestId_)) {
        return false;
    }
    if (!parcel.ReadUint8(status_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerSendRspParam::ConvertToSsapsSendRspParam(SsapsSendRspParam &param) const
{
    param.requestId = requestId_;
    param.status = (SleSsapErrorCode)status_;
    param.valueLen = length_;
    param.value = data_.get();
}

SleErrorCode SsapServerSendRspParam::CheckSsapsSendRspParam(const SsapsSendRspParam &param)
{
    SLE_ASSERT_AND_RETURN_RET_LOG(param.status >= ERROR_CODE_SSAP_INVALID_PDU && param.status < ERROR_CODE_SSAP_VALUE_OUT_OF_RANGE,
        SLE_ERR_INVALID_PARAM, "param server response status error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.value, SLE_ERR_INVALID_PARAM,
        "param server response value ptr not init error!");
    return SLE_NO_ERROR;
}

// SsapServerNotifyParam
SsapServerNotifyParam::SsapServerNotifyParam(const SsapsNotifyParam &param)
{
    handle_ = param.handle;
    type_ = param.type;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }
}

bool SsapServerNotifyParam::Marshalling(Parcel &parcel) const
{
    if(!parcel.WriteUint16(handle_)) {
        return false;
    }
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerNotifyParam *SsapServerNotifyParam::Unmarshalling(Parcel &parcel)
{
    SsapServerNotifyParam *param = new SsapServerNotifyParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerNotifyParam::ReadFromParcel(Parcel &parcel)
{
    if (!parcel.ReadUint16(handle_)) {
        return false;
    }
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerNotifyParam::ConvertToSsapsNotifyParam(SsapsNotifyParam &param) const
{
    param.handle = handle_;
    param.type = (SsapPropertyType)type_;
    param.valueLen = length_;
    param.value = data_.get();
}

SleErrorCode SsapServerNotifyParam::CheckSsapsNotifyParam(const SsapsNotifyParam &param)
{
    SLE_ASSERT_AND_RETURN_RET_LOG(param.type == SSAP_PROPERTY_TYPE_VALUE_TYPE,
        SLE_ERR_INVALID_PARAM, "param server notify type error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.valueLen != 0, SLE_ERR_INVALID_PARAM,
        "param server notify value length error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.value, SLE_ERR_INVALID_PARAM,
        "param server notify value ptr not init error!");
    return SLE_NO_ERROR;
}

// SsapServerNotyfyByUuidParam
SsapServerNotyfyByUuidParam::SsapServerNotyfyByUuidParam(const SsapsNotyfyByUuidParam &param)
{
    Uuid uuid(param.uuid);
    uuid_ = uuid;
    startHandle_ = param.startHandle;
    endHandle_ = param.endHandle;
    type_ = param.type;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }
}

bool SsapServerNotyfyByUuidParam::Marshalling(Parcel &parcel) const
{
    if (!parcel.WriteParcelable(&uuid_)) {
        return false;
    }
    if(!parcel.WriteUint16(startHandle_)) {
        return false;
    }
    if(!parcel.WriteUint16(endHandle_)) {
        return false;
    }
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerNotyfyByUuidParam *SsapServerNotyfyByUuidParam::Unmarshalling(Parcel &parcel)
{
    SsapServerNotyfyByUuidParam *param = new SsapServerNotyfyByUuidParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerNotyfyByUuidParam::ReadFromParcel(Parcel &parcel)
{
    std::shared_ptr<Uuid> uuid(parcel.ReadParcelable<Uuid>());
    if (!uuid) {
        return false;
    }
    uuid_ = *uuid;

    if (!parcel.ReadUint16(startHandle_)) {
        return false;
    }
    if (!parcel.ReadUint16(endHandle_)) {
        return false;
    }
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerNotyfyByUuidParam::ConvertToSsapsNotyfyByUuidParam(SsapsNotyfyByUuidParam &param) const
{
    param.uuid = uuid_.ConvertToSleUuid();
    param.startHandle = startHandle_;
    param.endHandle = endHandle_;
    param.type = (SsapPropertyType)type_;
    param.valueLen = length_;
    param.value = data_.get();
}

SleErrorCode SsapServerNotyfyByUuidParam::CheckSsapsNotyfyByUuidParam(const SsapsNotyfyByUuidParam &param)
{
    SleErrorCode ret = Uuid::CheckSleUuid(param.uuid);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_NO_ERROR, SLE_ERR_INVALID_PARAM,
        "param server notify by uuid property uuid error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.startHandle <= param.endHandle,
        SLE_ERR_INVALID_PARAM, "param server notify by uuid handle error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.type == SSAP_PROPERTY_TYPE_VALUE_TYPE,
        SLE_ERR_INVALID_PARAM, "param server notify by uuid type error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.valueLen != 0,
        SLE_ERR_INVALID_PARAM, "param server notify by uuid value length error!");
    SLE_ASSERT_AND_RETURN_RET_LOG(param.value, SLE_ERR_INVALID_PARAM,
        "param server notify by uuid value ptr not init error!");
    return SLE_NO_ERROR;
}

// SsapServerReqReadCbParam
SsapServerReqReadCbParam::SsapServerReqReadCbParam(const SsapsReqReadCbParam &param)
{
    requestId_ = param.requestId;
    handle_ = param.handle;
    type_ = param.type;
    needRsp_ = param.needRsp;
    needAuthorize_ = param.needAuthorize;
}

bool SsapServerReqReadCbParam::Marshalling(Parcel &parcel) const
{
    if(!parcel.WriteUint16(requestId_)) {
        return false;
    }
    if(!parcel.WriteUint16(handle_)) {
        return false;
    }
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    if(!parcel.WriteBool(needRsp_)) {
        return false;
    }
    if(!parcel.WriteBool(needAuthorize_)) {
        return false;
    }
    return true;
}

SsapServerReqReadCbParam *SsapServerReqReadCbParam::Unmarshalling(Parcel &parcel)
{
    SsapServerReqReadCbParam *param = new SsapServerReqReadCbParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerReqReadCbParam::ReadFromParcel(Parcel &parcel)
{
    if (!parcel.ReadUint16(requestId_)) {
        return false;
    }
    if (!parcel.ReadUint16(handle_)) {
        return false;
    }
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    if(!parcel.ReadBool(needRsp_)) {
        return false;
    }
    if(!parcel.ReadBool(needAuthorize_)) {
        return false;
    }
    return true;
}

void SsapServerReqReadCbParam::ConvertToSsapsReqReadCbParam(SsapsReqReadCbParam &value) const
{
    value.requestId = requestId_;
    value.handle = handle_;
    value.type = (SsapPropertyType)type_;
    value.needRsp = needRsp_;
    value.needAuthorize = needAuthorize_;
}

// SsapServerReqWriteCbParam
SsapServerReqWriteCbParam::SsapServerReqWriteCbParam(const SsapsReqWriteCbPara &param)
{
    requestId_ = param.requestId;
    handle_ = param.handle;
    type_ = param.type;
    needRsp_ = param.needRsp;
    needAuthorize_ = param.needAuthorize;
    length_ = param.valueLen;
    if (param.value != nullptr && length_ != 0) {
        data_ = std::make_unique<uint8_t[]>(length_);
        (void)memcpy_s(data_.get(), length_, param.value, length_);
    } else {
        data_ = nullptr;
        length_ = 0;
    }

}

bool SsapServerReqWriteCbParam::Marshalling(Parcel &parcel) const
{
    if(!parcel.WriteUint16(requestId_)) {
        return false;
    }
    if(!parcel.WriteUint16(handle_)) {
        return false;
    }
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    if(!parcel.WriteBool(needRsp_)) {
        return false;
    }
    if(!parcel.WriteBool(needAuthorize_)) {
        return false;
    }
    if(!parcel.WriteUint16(length_)) {
        return false;
    }
    for (size_t i = 0; i < length_; i++) {
        if(!parcel.WriteUint8(data_[i])) {
            return false;
        }
    }
    return true;
}

SsapServerReqWriteCbParam *SsapServerReqWriteCbParam::Unmarshalling(Parcel &parcel)
{
    SsapServerReqWriteCbParam *param = new SsapServerReqWriteCbParam();
    if (param != nullptr && !param->ReadFromParcel(parcel)) {
        delete param;
        param = nullptr;
    }
    return param;
}

bool SsapServerReqWriteCbParam::ReadFromParcel(Parcel &parcel)
{
    if (!parcel.ReadUint16(requestId_)) {
        return false;
    }
    if (!parcel.ReadUint16(handle_)) {
        return false;
    }
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    if(!parcel.ReadBool(needRsp_)) {
        return false;
    }
    if(!parcel.ReadBool(needAuthorize_)) {
        return false;
    }
    if (!parcel.ReadUint16(length_)) {
        return false;
    }
    if (length_ != 0) {
        uint8_t data[length_];
        for (size_t i = 0; i < length_; i++) {
            if (!parcel.ReadUint8(data[i])) {
                return false;
            }
        }
        data_ = std::make_unique<uint8_t[]>(length_);
        if (memcpy_s(data_.get(), length_, data, length_) != SLE_NO_ERROR) {
            return false;
        }
    }
    return true;
}

void SsapServerReqWriteCbParam::ConvertToSsapsReqWriteCbPara(SsapsReqWriteCbPara &value) const
{
    value.requestId = requestId_;
    value.handle = handle_;
    value.type = (SsapPropertyType)type_;
    value.needRsp = needRsp_;
    value.needAuthorize = needAuthorize_;
    value.valueLen = length_;
    value.value = data_.get();
}
} // SleStandard
} // NearLink
} // OHOS